#!/usr/bin/env bash

SetBaseDir() {
  BASEDIR=$1
  if [[ ! $BASEDIR = /* ]]; then
    # Relative
    BASEDIR=$(pwd)/${BASEDIR}
  fi
}

SetBaseDir $(dirname $0)
INSTALL=0
UPDATE=0
INSTALLER_ARGS=''
RUN_VIM="vim -N --clean --not-a-term"
RUN_TEST="${RUN_VIM} -S lib/run_test.vim"
BASEDIR_CMD='py3 pass'

# 1 is stdout
out_fd=1

while [ -n "$1" ]; do
  case "$1" in
    "--basedir")
      shift
      SetBaseDir $1
      shift
      BASEDIR_CMD="let g:vimspector_base_dir='${BASEDIR}'"
      ;;
    "--install")
      INSTALL=1
      shift
      ;;
    "--install-method")
      shift
      INSTALL=$1
      shift
      ;;
    "--update")
      UPDATE=1
      shift
      ;;
    "--report")
      shift
      VIMSPECTOR_TEST_STDOUT=$1
      shift
      ;;
    "--quiet")
      shift
      # send the output to /dev/null
      # https://stackoverflow.com/a/47553900
      # Note we can't use {out_fd} here because the bash version in CI is too
      # old on macOS
      out_fd=3
      exec 3>/dev/null
      INSTALLER_ARGS="${INSTALLER_ARGS} --quiet"
      ;;
    "--")
      shift
      break
      ;;
    "--help")
      shift
      echo "$(basename $0) [--basedir <basedir>] [--report output] [--quiet] [--install] <optional list of tests in form file:func>"
      echo ""
      echo " --basedir <basedir>     path to runtime directory like the optino to install_gadget.py"
      echo " --install               run install_gadget.py, useful with --basedir"
      echo " --report <messages|all> which logs to dump to stdout after a test"
      echo " --quiet                 suppress vim's stdout"
      echo "e.g.: "
      echo " - run all tests: $0"
      echo " - run specific tests script: $0 signature_help.test.vim"
      echo " - run specific tests fun: $0 signature_help.test.vim:Test_signatures_TopLine\(\)"
      echo " - run all tests in a clean env: $0 --basedir \$(mktemp -d) --install"
      exit 0
      ;;
    *)
      break
      ;;
  esac
done

# We use fd 3 for vim's output. Send it to stdout if not already redirected
# Note: can't use ${out_fd} in a redirect because redirects happen before
# variable substitution
if [ "${out_fd}" = "1" ]; then
  exec 3>&1
fi

if [ "$INSTALL" = "1" ] || [ "$INSTALL" = "script" ]; then
  if ! python3 $(dirname $0)/install_gadget.py \
               --basedir ${BASEDIR} \
               ${INSTALLER_ARGS} \
               --all \
               --force-enable-csharp; then
    echo "Script installation reported errors" >&2
    exit 1
  fi
fi

if [ "$INSTALL" = "1" ] || [ "$INSTALL" = "vim" ]; then
  if ! $RUN_VIM -u $(dirname $0)/tests/vimrc \
               --cmd "${BASEDIR_CMD}" \
               -c 'autocmd User VimspectorInstallSuccess qa!' \
               -c 'autocmd User VimspectorInstallFailed cquit!' \
               -c "VimspectorInstall --all netcoredbg"; then
    echo "Vim installation reported errors" >&2
    exit 1
  fi
fi

if [ "$UPDATE" = "1" ]; then
  if ! $RUN_VIM -u $(dirname $0)/tests/vimrc \
               --cmd "${BASEDIR_CMD}" \
               -c 'autocmd User VimspectorInstallSuccess qa!' \
               -c 'autocmd User VimspectorInstallFailed cquit!' \
               -c "VimspectorUpdate"; then
    echo "Vim update reported errors" >&2
    exit 1
  fi
fi


if [ -z "$VIMSPECTOR_MIMODE" ]; then
  if which lldb >/dev/null 2>&1; then
    export VIMSPECTOR_MIMODE=lldb
  elif which gdb >/dev/null 2>&1; then
    export VIMSPECTOR_MIMODE=gdb
  else
    echo "Couldn't guess VIMSPECTOR_MIMODE. Need lldb or gdb in path"
    exit 1
  fi
fi

echo "Testing with:"
echo " * VIMSPECTOR_MIMODE=$VIMSPECTOR_MIMODE"
echo " * RUN_VIM=$RUN_VIM"
echo " * RUN_TEST=$RUN_TEST"
echo " * BASEDIR=$BASEDIR"
echo " * BASEDIR_CMD=$BASEDIR_CMD"


echo "%SETUP - Building test programs..."
set -e
  pushd tests/testdata/cpp/simple
    make clean all
  popd
  pushd support/test/csharp
    dotnet build
  popd
set +e
echo "%DONE - built test programs"

# Start
pushd $(dirname $0)/tests > /dev/null
echo "Running Vimspector Vim tests"

RESULT=0

TESTS="$@"

if [ -z "$TESTS" ]; then
  TESTS=*.test.vim
fi

for t in ${TESTS}; do
  echo ""
  echo "%RUN: $t"

  # split on : into fileName and testName
  IFS=: read -s t T <<< "$t"

  TESTLOGDIR=${BASEDIR}/tests/logs/$t

  if ${RUN_TEST} --cmd "${BASEDIR_CMD}" \
                 --cmd 'au SwapExists * let v:swapchoice = "e"' $t $T \
                 >&3\
     && [ -f $t.res ];  then
    echo "%PASS: $t PASSED"
  else
    echo "%FAIL: $t FAILED - see $TESTLOGDIR"
    RESULT=1
  fi

  rm -rf $TESTLOGDIR
  mkdir -p $TESTLOGDIR
  ${RUN_VIM} --version > ${TESTLOGDIR}/vimversion
  if [ "$VIMSPECTOR_TEST_STDOUT" = "messages" ]; then
    if [ -f messages ]; then
      echo "%MESSAGES"
      cat messages
      echo "%END"
    else
      echo "%MESSAGES"
      echo "No messages found"
      echo "%END"
    fi
  fi

  for l in messages debuglog test.log *.testlog; do
    # In CI we can't view the output files, so we just have to cat them
    if [ -f $l ]; then
      if [ "$VIMSPECTOR_TEST_STDOUT" = "all" ]; then
        echo ""
        echo ""
        echo "*** START: $l ***"
        cat $l
        echo "*** END: $l ***"
      fi
      mv $l $TESTLOGDIR
    fi
  done

  rm -f $t.res
done

# close out_fd if it's not stdout/stderr/
(( out_fd > 2 )) && exec 3>&-


echo "Done running tests"
popd > /dev/null

echo ""
echo "All done. Exit with ${RESULT}"

exit $RESULT
